﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="InvokeMethodExpressionTokenizerTests.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the InvokeMethodExpressionTokenizerTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Windows
{
    using System;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Photon.Testing;
    using Photon.Windows.Input;

    [TestClass]
    public class InvokeMethodExpressionTokenizerTests
    {
        [TestMethod]
        public void When_Read_Method()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier)
                }, list);
        }

        [TestMethod]
        public void When_Read_Method_With_Brackets()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method()").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Read_Method_With_Brackets_And_Parameter_Positions()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method(,,,)").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    InvokeMethodExpressionToken.Comma,
                    InvokeMethodExpressionToken.Comma,
                    InvokeMethodExpressionToken.Comma,
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Read_Method_With_Brackets_And_Parameter_Types()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method(int,string,bool)").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    new InvokeMethodExpressionToken("int", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("string", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("bool", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Read_Method_With_Brackets_And_Parameter_Types_That_Have_Dotted_Identifiers()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method(System.Int32, System.Double)").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    new InvokeMethodExpressionToken("System", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Dot,
                    new InvokeMethodExpressionToken("Int32", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("System", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Dot,
                    new InvokeMethodExpressionToken("Double", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Read_Method_With_Brackets_And_Nullable_Parameter_Types()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method(int?,string,bool?)").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    new InvokeMethodExpressionToken("int", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.QuestionMark,
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("string", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("bool", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.QuestionMark,
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Read_Method_With_Generic_Arguments()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method(IList<string>)").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    new InvokeMethodExpressionToken("IList", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.LessThan,
                    new InvokeMethodExpressionToken("string", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.GreaterThan,
                    InvokeMethodExpressionToken.CloseBracket
                }, list);

        }

        [TestMethod]
        public void When_Identifier_Is_Invalid()
        {
            AssertException.Throws<FormatException>(() => InvokeMethodExpressionTokenizer.Tokenize("1Method").ToList());
            AssertException.Throws<FormatException>(() => InvokeMethodExpressionTokenizer.Tokenize("Test(1Type)").ToList());
        }

        [TestMethod]
        public void When_Expression_Is_Empty()
        {
            Assert.AreEqual(0, InvokeMethodExpressionTokenizer.Tokenize("").ToList().Count);
            Assert.AreEqual(0, InvokeMethodExpressionTokenizer.Tokenize("      \r\t\n").ToList().Count);
        }

        [TestMethod]
        public void When_Skipping_White_Space()
        {
            var list = InvokeMethodExpressionTokenizer.Tokenize("Method   (    System   .   Int32   ,   System   .    Double   ) ").ToList();
            CollectionAssert.AreEqual(new[]
                {
                    new InvokeMethodExpressionToken("Method", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.OpenBracket,
                    new InvokeMethodExpressionToken("System", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Dot,
                    new InvokeMethodExpressionToken("Int32", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Comma,
                    new InvokeMethodExpressionToken("System", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.Dot,
                    new InvokeMethodExpressionToken("Double", InvokeMethodExpressionTokenType.Identifier),
                    InvokeMethodExpressionToken.CloseBracket
                }, list);
        }
    }
}
